﻿using EnterpriseWebsiteUtil.Attributes;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

namespace EnterpriseWebsiteUtil.Helper
{
    public class LangSplitHelper
    {
        public List<object> SplitByLang<T>(T obj) where T : class
        {
            var result = new List<object>();
            var type = obj.GetType();
            var langSplitAttr = type.GetCustomAttribute<LangSplitAttribute>();
            if (langSplitAttr == null)
            {
                return result;
            }
            var langProps = type.GetProperties().Where(prop => prop.GetCustomAttribute<LangSplitFieldAttribute>() != null);
            foreach (var lang in Enum.GetValues(typeof(LangType)).Cast<LangType>())
            {
                var langData = new Dictionary<string, object>();
                langData.Add("lang", lang.ToString());
                var langPropsData = new Dictionary<string, object>();
                foreach (var prop in langProps)
                {
                    var langSplitFieldAttr = prop.GetCustomAttribute<LangSplitFieldAttribute>();
                    if (langSplitFieldAttr.Lang == lang)
                    {
                        var propName = langSplitFieldAttr.Field;
                        var propValue = prop.GetValue(obj);
                        langPropsData.Add(propName, propValue);
                    }
                }
                langData.Add("data", langPropsData);
                result.Add(langData);
            }

            // 遍历所有属性，将没有 LangSplitField 特性的属性的值赋值到所有分类中
            var allProps = type.GetProperties();
            foreach (var prop in allProps)
            {
                var langSplitFieldAttr = prop.GetCustomAttribute<LangSplitFieldAttribute>();
                if (langSplitFieldAttr == null)
                {
                    var propName = prop.Name;
                    var propValue = prop.GetValue(obj);
                    foreach (var lang in Enum.GetValues(typeof(LangType)).Cast<LangType>())
                    {
                        var langData = result.FirstOrDefault(d => d.GetType().GetProperty("lang").GetValue(d).ToString() == lang.ToString());
                        if (langData != null)
                        {
                            var langPropsData = (Dictionary<string, object>)langData.GetType().GetProperty("data").GetValue(langData);
                            langPropsData.Add(propName, propValue);
                        }
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// 根据LangSplitFieldAttribute特性，重组成新字段
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="lang"></param>
        /// <returns></returns>
        public IDictionary<string, object> ConvertToLang<T>(T obj, LangType lang,Type type = null)
        {
            var result = new Dictionary<string, object>();
            type = type == null ? typeof(T): type;
            foreach (var prop in type.GetProperties())
            {
                var attr = prop.GetCustomAttribute<LangSplitFieldAttribute>();
                if (attr != null)
                {
                    if (attr.Lang == lang)
                    {
                        var fieldValue = prop.GetValue(obj);
                        if (fieldValue is string stringValue && !string.IsNullOrEmpty(attr.FilterValue))
                        {
                            fieldValue = Regex.Replace(stringValue, attr.FilterValue, "");
                        }
                        if (fieldValue != null || !string.IsNullOrEmpty(attr.Field))
                        {
                            result[attr.Field] = (fieldValue == null  || string.IsNullOrEmpty((string)fieldValue)) ? GetFieldValue(obj, attr.EmptyReplace, attr.Field) : fieldValue;
                        }
                    }
                }
                else
                {
                    var propValue = prop.GetValue(obj);
                    if (propValue == null)
                        continue;
                    if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(List<>))
                    {
                        var listResult = new List<object>();
                        foreach (var item in (IEnumerable)propValue)
                        {
                            var itemResult = ConvertToLang(item, lang, item.GetType());
                            listResult.Add(itemResult);
                        }
                        result[prop.Name] = listResult;
                    }
                    else
                    {
                        result[prop.Name] = propValue;
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// 列表转换
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="lang"></param>
        /// <returns></returns>
        public List<IDictionary<string, object>> ConvertToLangList(IEnumerable obj, LangType lang)
        {
            var resultList = new List<IDictionary<string, object>>();
            foreach (var item in obj)
            {
                var itemResult = ConvertToLang(item, lang, item.GetType());
                resultList.Add(itemResult);
            }
            return resultList;
        }

        public List<IDictionary<string, object>> ConvertToLang<T>(IEnumerable<T> obj, LangType lang)
        {
            return ConvertToLangList(obj,lang);
        }

        private object GetFieldValue(object obj, LangType lang, string fieldName)
        {
            var type = obj.GetType();

            var prop = type.GetProperty(fieldName);
            if (prop == null)
                return null;

            var attr = prop.GetCustomAttribute<LangSplitFieldAttribute>();
            if (attr != null && attr.Lang != lang)
            {
                return null;
            }
            //?? GetFieldValue(obj, attr.EmptyReplace, attr.Field);
            return prop.GetValue(obj);
        }
    }
}
